#include "spi.h"

SPI_HandleTypeDef st7789_hspi;
DMA_HandleTypeDef st7789_dma_spi_tx;
void st7789_spi_init(void)
{

  st7789_hspi.Instance = SPI1;
  st7789_hspi.Init.Mode = SPI_MODE_MASTER;
  st7789_hspi.Init.Direction = SPI_DIRECTION_1LINE;
  st7789_hspi.Init.DataSize = SPI_DATASIZE_8BIT;
  st7789_hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
  st7789_hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
  st7789_hspi.Init.NSS = SPI_NSS_SOFT;
  st7789_hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  st7789_hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
  st7789_hspi.Init.TIMode = SPI_TIMODE_DISABLE;
  st7789_hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  st7789_hspi.Init.CRCPolynomial = 10;
  
  if (HAL_SPI_Init(&st7789_hspi) != HAL_OK)
  {
    Error_Handler();
  }
}

void st7789_spi_tx_byte(uint8_t _byte)
{
  LL_SPI_SetDataWidth(st7789_hspi.Instance, LL_SPI_DATAWIDTH_8BIT);
  st7789_hspi.Init.DataSize = SPI_DATASIZE_8BIT;
  HAL_SPI_Transmit(&st7789_hspi, &_byte, 1, 10);
}

void st7789_spi_tx_half_word(uint16_t _half_word)
{
  LL_SPI_SetDataWidth(st7789_hspi.Instance, LL_SPI_DATAWIDTH_16BIT);
  st7789_hspi.Init.DataSize = SPI_DATASIZE_16BIT;
  HAL_SPI_Transmit(&st7789_hspi, (uint8_t*)&_half_word, 1, 10);
}

uint8_t st7789_spi_is_busy(void)
{
  return HAL_SPI_GetState(&st7789_hspi) != HAL_SPI_STATE_READY;
}

void st7789_spi_tx_dma(uint16_t *color, uint16_t len)
{
    LL_SPI_SetDataWidth(st7789_hspi.Instance, LL_SPI_DATAWIDTH_16BIT);
    st7789_hspi.Init.DataSize = SPI_DATASIZE_16BIT;
    HAL_SPI_Transmit_DMA(&st7789_hspi, (uint8_t *)color, len);
}


void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA7     ------> SPI1_MOSI 
    */
    GPIO_InitStruct.Pin = TFT_CSK_Pin|TFT_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_TX Init */
    st7789_dma_spi_tx.Instance = DMA2_Stream3;
    st7789_dma_spi_tx.Init.Channel = DMA_CHANNEL_3;
    st7789_dma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    st7789_dma_spi_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    st7789_dma_spi_tx.Init.MemInc = DMA_MINC_ENABLE;
    st7789_dma_spi_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    st7789_dma_spi_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    st7789_dma_spi_tx.Init.Mode = DMA_NORMAL;
    st7789_dma_spi_tx.Init.Priority = DMA_PRIORITY_LOW;
    st7789_dma_spi_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&st7789_dma_spi_tx) != HAL_OK)
    {
      Error_Handler();
    }
    __HAL_LINKDMA(spiHandle,hdmatx,st7789_dma_spi_tx);
  }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{

  if(spiHandle->Instance==SPI1)
  {
    __HAL_RCC_SPI1_CLK_DISABLE();
  
    /**SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA7     ------> SPI1_MOSI 
    */
    HAL_GPIO_DeInit(GPIOA, TFT_CSK_Pin|TFT_SDA_Pin);
    HAL_DMA_DeInit(spiHandle->hdmatx);
  }
}